﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LL.Common;

namespace LL.Data.FluentData
{
    /// <summary>
    /// Sql翻译器
    /// </summary>
    public class SqlTranslator : ISqlTranslator
    {
        private static SqlTranslator _instance;
        public static SqlTranslator Instance
        {
            get { return _instance ?? (_instance = new SqlTranslator()); }
        }

        /// <summary>
        /// 条件组合翻译Sql语句（待完善）
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public TranslationResult Translate(QueryConditions queryConditions)
        {
            var result = new TranslationResult { WhereStatement = "" };
            if (queryConditions == null || queryConditions.Count < 1)
                return result;

            result.WhereStatement = TranslateGroup(queryConditions, result.Parameters);
            return result;
        }

        /// <summary>
        /// 翻译一组条件
        /// </summary>
        public static string TranslateGroup(IConditionGroup groups, IList<object> parameters)
        {
            if (groups == null || groups.Count < 1)
                return String.Empty;

            var builder = new StringBuilder();
            foreach (var item in groups.Conditions)
            {
                if (item is Condition)
                {
                    //翻译单个条件
                    builder.AppendFormat("{0}{1}",
                        builder.Length > 0 ? TranslateRelation(item.Relation) : "",
                        TranslateCondition(item.As<Condition>().ConditionItem, parameters));
                    continue;
                }
                if (item is IConditionGroup)
                {
                    builder.AppendFormat("{0}({1})",
                        builder.Length > 0 ? TranslateRelation(item.Relation) : "",
                        TranslateGroup(item.As<IConditionGroup>(), parameters));
                }
            }
            return builder.ToString();
        }

        /// <summary>
        /// 翻译单个条件
        /// </summary>
        /// <param name="item1"></param>
        /// <returns></returns>
        public static string TranslateCondition(IConditionItem item1, IList<object> parameters)
        {
            if (item1 is KeyValueCondition)
            {
                var c = item1 as KeyValueCondition;
                return string.Format("{0} {1} {3}{2}{4}", c.ColumnName, TranslateOperator(c.Operator),
                    GetValue(c.Operator, c.Value, parameters), GetLeft(c.Operator), GetRight(c.Operator));
            }
            if (item1 is OriginalStringCondition)
            {
                var c = item1 as OriginalStringCondition;
                return c.where;
            }
            return String.Empty;
        }

        private static object GetValue(Comparison op, object value, IList<object> parameters)
        {
            if (op == Comparison.In)
            {
                if (!(value is IEnumerable))
                    throw new InvalidOperationException("使用In运算符，参数需要为集合类型");
                var builder = new StringBuilder();
                foreach (object parameter in value.As<IEnumerable>())
                {
                    parameters.Add(parameter);
                    builder.AppendFormat("@{0},", parameters.Count - 1);
                }
                return builder.ToString(0, builder.Length - 1);
            }
            parameters.Add(value);
            return "@" + (parameters.Count - 1);
        }

        private static object GetLeft(Comparison compareOperator)
        {
            switch (compareOperator)
            {
                case Comparison.NotContains:
                case Comparison.NotStartsWith:
                case Comparison.StartsWith:
                case Comparison.Contains:
                    return "'%'+";
                case Comparison.In:
                    return "(";
            }
            return null;
        }

        private static object GetRight(Comparison compareOperator)
        {
            switch (compareOperator)
            {
                case Comparison.NotContains:
                case Comparison.NotEndsWith:
                case Comparison.EndsWith:
                case Comparison.Contains:
                    return "+'%'";
                case Comparison.In:
                    return ")";
            }
            return null;
        }

        /// <summary>
        /// 翻译Sql关系运算符
        /// </summary>
        /// <param name="relation"></param>
        /// <returns></returns>
        public static string TranslateRelation(Relation relation)
        {
            if (relation == Relation.And)
                return " AND ";
            return " OR ";
        }

        /// <summary>
        /// 翻译Sql运算符
        /// </summary>
        /// <param name="op"></param>
        /// <returns></returns>
        public static string TranslateOperator(Comparison op)
        {
            switch (op)
            {
                case Comparison.Equal:
                    return "=";
                case Comparison.Greater:
                    return ">";
                case Comparison.GreaterEqual:
                    return ">=";
                case Comparison.Less:
                    return "<";
                case Comparison.LessEqual:
                    return "<=";
                case Comparison.NotEqual:
                    return "<>";
                case Comparison.IsNull:
                    return "IS NULL";
                case Comparison.IsNotNull:
                    return "IS NOT NULL";
                case Comparison.In:
                    return "IN";
                case Comparison.Contains:
                case Comparison.StartsWith:
                case Comparison.EndsWith:
                    return "LIKE";
                case Comparison.NotContains:
                case Comparison.NotStartsWith:
                case Comparison.NotEndsWith:
                    return "NOT LIKE";
            }
            return "";
        }

        /// <summary>
        /// 翻译Sql排序
        /// </summary>
        public static string TranslateOrder(IList<FiledSort> orders)
        {
            if (orders.IsNullOrEmpty())
                return String.Empty;
            var bulider = new StringBuilder();
            foreach (var filedSort in orders)
            {
                if (filedSort.Direction == SortDirection.Asc)
                {
                    bulider.Append(filedSort.Filed + ',');
                    continue;
                }
                bulider.AppendFormat("{0} DESC,", filedSort.Filed);
            }
            //去掉最后一个逗号
            return bulider.ToString(0, bulider.Length - 1);
        }
    }
}
